package client

import (
	"fmt"
	"net"
	"sync"
	"time"

	"go.uber.org/zap"

	consts "go-war3proxy/pkg/const"
	pb "go-war3proxy/pkg/proto"
	"go-war3proxy/pkg/utils"
)

// ConnectionWar3ProxyServer 负责与war3ProxyServer建立tcp连接，接收服务器指令和IP列表
type ConnectionWar3ProxyServer struct {
	client *Client
	logger *zap.Logger
	war3IP string
	conn   net.Conn
	mutex  sync.RWMutex
}

// NewConnectionWar3ProxyServer 创建新的连接管理器
func NewConnectionWar3ProxyServer(client *Client, logger *zap.Logger) *ConnectionWar3ProxyServer {
	return &ConnectionWar3ProxyServer{
		client: client,
		logger: logger.With(zap.String("component", "connection_server")),
	}
}

// Start 启动连接管理器
func (cwps *ConnectionWar3ProxyServer) Start() {
	for {
		if err := cwps.connectAndRun(); err != nil {
			cwps.logger.Error("连接运行失败", zap.Error(err))
		}

		// 连接断开后等待一段时间重试
		time.Sleep(5 * time.Second)
	}
}

// connectAndRun 连接服务器并运行消息处理循环
func (cwps *ConnectionWar3ProxyServer) connectAndRun() error {
	address := fmt.Sprintf("%s:%d", cwps.client.GetServerIP(), cwps.client.GetServerPort())

	cwps.logger.Info("连接War3代理服务器", zap.String("address", address))

	conn, err := net.DialTimeout("tcp", address, time.Duration(consts.TimeoutSecond)*time.Second)
	if err != nil {
		return fmt.Errorf("连接服务器失败: %w", err)
	}

	cwps.mutex.Lock()
	cwps.conn = conn
	cwps.mutex.Unlock()

	defer func() {
		cwps.mutex.Lock()
		cwps.conn = nil
		cwps.mutex.Unlock()
		conn.Close()
	}()

	cwps.logger.Info("连接War3代理服务器成功", zap.String("address", address))

	// 发送客户端连接消息
	connectMessage := &pb.War3Message{
		Type:    pb.MessageType_CLIENT_CONNECT,
		Payload: nil,
	}

	if err := utils.SendProtobufMessage(conn, connectMessage, cwps.logger); err != nil {
		return fmt.Errorf("发送连接消息失败: %w", err)
	}

	// 消息处理循环
	for {
		message, err := utils.ReceiveProtobufMessage(conn, cwps.logger)
		if err != nil {
			return fmt.Errorf("接收消息失败: %w", err)
		}

		if err := cwps.handleServerMessage(message); err != nil {
			cwps.logger.Error("处理服务器消息失败", zap.Error(err))
			return err
		}
	}
}

// handleServerMessage 处理服务器消息
func (cwps *ConnectionWar3ProxyServer) handleServerMessage(message *pb.War3Message) error {
	switch message.Type {
	case pb.MessageType_CLIENT_CONNECT_RESULT:
		return cwps.handleInitialConnection(message)
	case pb.MessageType_CLIENT_LIST_UPDATE:
		return cwps.handleClientListUpdate(message)
	case pb.MessageType_NOTIFICATION:
		return cwps.handleNotification()
	case pb.MessageType_DATA_FORWARD:
		return cwps.handleDataForward(message)
	default:
		return fmt.Errorf("不支持的消息类型: %s", message.Type.String())
	}
}

// handleInitialConnection 处理初始连接响应
func (cwps *ConnectionWar3ProxyServer) handleInitialConnection(message *pb.War3Message) error {
	ipAssignment := message.GetPayload().(*pb.War3Message_IpAssignment).IpAssignment
	cwps.war3IP = ipAssignment.AssignedIp

	cwps.logger.Info("收到War3代理服务器分配的IP", zap.String("war3_ip", cwps.war3IP))

	// 为其他客户端创建War3Server
	for _, otherWar3IP := range ipAssignment.OtherIps {
		if otherWar3IP == "" {
			continue
		}

		cwps.logger.Info("为其他War3IP创建War3Server", zap.String("other_war3_ip", otherWar3IP))

		war3Server := NewWar3Server(otherWar3IP, cwps, cwps.logger)
		cwps.client.AddWar3Server(otherWar3IP, war3Server)

		go war3Server.Start()
	}

	return nil
}

// handleClientListUpdate 处理客户端列表更新
func (cwps *ConnectionWar3ProxyServer) handleClientListUpdate(message *pb.War3Message) error {
	clientListUpdate := message.GetPayload().(*pb.War3Message_ClientListUpdate).ClientListUpdate

	// 获取当前所有War3Server
	currentServers := cwps.client.GetAllWar3Servers()

	// 添加新的War3Server
	for _, otherWar3IP := range clientListUpdate.ClientIps {
		if _, exists := currentServers[otherWar3IP]; !exists {
			cwps.logger.Info("添加新的War3Server", zap.String("other_war3_ip", otherWar3IP))

			war3Server := NewWar3Server(otherWar3IP, cwps, cwps.logger)
			cwps.client.AddWar3Server(otherWar3IP, war3Server)

			go war3Server.Start()
		}
	}

	// 移除不存在的War3Server
	updatedIPs := make(map[string]bool)
	for _, ip := range clientListUpdate.ClientIps {
		updatedIPs[ip] = true
	}

	for otherWar3IP := range currentServers {
		if !updatedIPs[otherWar3IP] {
			cwps.logger.Info("移除不存在的War3Server", zap.String("other_war3_ip", otherWar3IP))
			cwps.client.RemoveWar3Server(otherWar3IP)
		}
	}

	return nil
}

// handleNotification 处理通知消息
func (cwps *ConnectionWar3ProxyServer) handleNotification() error {
	// 启动一个新的goroutine来处理连接
	go func() {
		if err := cwps.provideWar3Connection(); err != nil {
			cwps.logger.Error("提供War3连接失败", zap.Error(err))
		}
	}()

	return nil
}

// provideWar3Connection 提供War3连接
func (cwps *ConnectionWar3ProxyServer) provideWar3Connection() error {
	// 连接本地War3游戏
	localConn, err := net.DialTimeout("tcp",
		fmt.Sprintf("%s:%d", cwps.client.GetWar3LocalIP(), consts.War3Port),
		time.Duration(consts.TimeoutSecond)*time.Second)
	if err != nil {
		return fmt.Errorf("连接本地War3游戏失败: %w", err)
	}
	defer localConn.Close()

	cwps.logger.Info("连接本地War3游戏成功",
		zap.String("local_ip", cwps.client.GetWar3LocalIP().String()),
		zap.Int("port", consts.War3Port))

	// 连接War3代理服务器
	proxyConn, err := net.DialTimeout("tcp",
		fmt.Sprintf("%s:%d", cwps.client.GetServerIP(), cwps.client.GetServerPort()),
		time.Duration(consts.TimeoutSecond)*time.Second)
	if err != nil {
		return fmt.Errorf("连接代理服务器失败: %w", err)
	}
	defer proxyConn.Close()

	cwps.logger.Info("连接War3代理服务器成功",
		zap.String("proxy_ip", cwps.client.GetServerIP()),
		zap.Int("proxy_port", cwps.client.GetServerPort()))

	// 发送PROVIDE_WAR3消息
	provideMessage := &pb.War3Message{
		Type:     pb.MessageType_PROVIDE_WAR3,
		SourceIp: cwps.war3IP,
		Payload:  nil,
	}

	if err := utils.SendProtobufMessage(proxyConn, provideMessage, cwps.logger); err != nil {
		return fmt.Errorf("发送PROVIDE_WAR3消息失败: %w", err)
	}

	cwps.logger.Info("发送PROVIDE_WAR3消息成功", zap.String("war3_ip", cwps.war3IP))

	// 开始双向数据转发
	done := make(chan struct{})

	go func() {
		utils.TransferData(localConn, proxyConn, cwps.logger)
		done <- struct{}{}
	}()

	go func() {
		utils.TransferData(proxyConn, localConn, cwps.logger)
		done <- struct{}{}
	}()

	// 等待任一方向完成
	<-done

	cwps.logger.Info("数据转发结束")
	return nil
}

// handleDataForward 处理数据转发消息
func (cwps *ConnectionWar3ProxyServer) handleDataForward(message *pb.War3Message) error {
	dataForward := message.GetPayload().(*pb.War3Message_DataForward).DataForward

	war3Server := cwps.client.GetWar3Server(message.TargetIp)
	if war3Server == nil {
		return fmt.Errorf("未找到War3Server: %s", message.TargetIp)
	}

	if len(dataForward.Data) > 0 {
		// 直接转发原始UDP数据
		war3Server.UDPSend(dataForward.Data)
	}

	return nil
}

// ForwardUdpDataToServer 转发UDP数据到服务器
func (cwps *ConnectionWar3ProxyServer) ForwardUdpDataToServer(otherWar3IP string, data []byte, len int) error {
	cwps.mutex.RLock()
	conn := cwps.conn
	cwps.mutex.RUnlock()

	if conn == nil {
		return fmt.Errorf("TCP连接为空，无法发送数据")
	}

	// 检查连接是否仍然有效
	if !cwps.isConnectionValid(conn) {
		return fmt.Errorf("TCP连接已关闭，无法发送数据")
	}

	dataForward := &pb.DataForward{
		FromIp: otherWar3IP,
		Data:   data[:len],
	}

	message := &pb.War3Message{
		Type:     pb.MessageType_DATA_FORWARD,
		SourceIp: otherWar3IP,
		TargetIp: cwps.war3IP,
		Payload:  &pb.War3Message_DataForward{DataForward: dataForward},
	}

	return utils.SendProtobufMessage(conn, message, cwps.logger)
}

// isConnectionValid 检查连接是否有效
func (cwps *ConnectionWar3ProxyServer) isConnectionValid(conn net.Conn) bool {
	if conn == nil {
		return false
	}

	// 检查连接是否已关闭
	return conn.LocalAddr() != nil && conn.RemoteAddr() != nil
}

// GetWar3IP 获取分配的War3 IP
func (cwps *ConnectionWar3ProxyServer) GetWar3IP() string {
	return cwps.war3IP
}
